package com.example.antlrdemo.service.impl;

import com.example.antlrdemo.antlr.array.ArrayInitLexer;
import com.example.antlrdemo.antlr.array.ArrayInitParser;
import com.example.antlrdemo.antlr.array.ShortToUnicodeString;
import com.example.antlrdemo.antlr.expr.ExprLexer;
import com.example.antlrdemo.antlr.expr.ExprParser;
import com.example.antlrdemo.antlr.hello.HelloLexer;
import com.example.antlrdemo.antlr.hello.HelloParser;
import com.example.antlrdemo.antlr.labeledexpr.CalculateLabeledExprVisitor;
import com.example.antlrdemo.antlr.labeledexpr.LabeledExprLexer;
import com.example.antlrdemo.antlr.labeledexpr.LabeledExprParser;
import com.example.antlrdemo.antlr.row.RowLexer;
import com.example.antlrdemo.antlr.row.RowParser;
import com.example.antlrdemo.service.AntlrService;
import lombok.extern.slf4j.Slf4j;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

/**
 * antlr语义解析
 */
@Service
@Slf4j
public class AntlrServiceImpl implements AntlrService {


    @Override
    public void paserHello(InputStream in){
        try {
            //新建一个CharStream，从标准输入流中读取数据
            ANTLRInputStream  antlrInputStream = new ANTLRInputStream (in);
            //新建一个 词法分析器，处理 输入流
            HelloLexer lexer = new HelloLexer(antlrInputStream);
            //新建 词法符号缓冲区，用于保存 词法分析器即将生成的词法符号
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            //新建 语法分析器，用于处理 词法符号缓冲区 的内容
            HelloParser helloParser = new HelloParser(tokens);
            //针对规则开始处理分析 r
            ParseTree context = helloParser.r();
            //生成解析数 LISP风格
            System.out.println(context.toStringTree(helloParser));
            System.out.println(tokens.getTokens());
/**         输出的token信息
 *             [
 *              [@0,0:4='Hello',<1>,1:0],
 *                          @0 表示词法符号的位置， 0:4 表示 输入的字符串的 0 - 4的位置
 *                          <1> 表示词法类型，  1:0 第 1行 下标是0的开始
 *
 *              [@1,6:10='asdds',<2>,1:6],
 *              [@2,11:10='<EOF>',<-1>,1:11]
 *              ]
 */

        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }

    @Override
    public void parserArray(InputStream in) {
        try {
            ANTLRInputStream  antlrInputStream = new ANTLRInputStream (in);
            ArrayInitLexer lexer = new ArrayInitLexer(antlrInputStream);
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            ArrayInitParser parser = new ArrayInitParser(tokens);
            ParseTree initTree = parser.init();

            //新建 一个通用的，能触回调方法的发语法分析树遍历器
            ParseTreeWalker walker = new ParseTreeWalker();

            //使用监听器 遍历语法分析树
            walker.walk(new ShortToUnicodeString(),initTree);
            //遍历完成，翻译结束
            System.out.println("");
/**         输出的token信息

 */

        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }

    @Override
    public void parserExpr(InputStream in) {
        try {
            ANTLRInputStream  antlrInputStream = new ANTLRInputStream (in);
            ExprLexer exprLexer= new ExprLexer(antlrInputStream);
            CommonTokenStream tokens = new CommonTokenStream(exprLexer);
            ExprParser parser = new ExprParser(tokens);
            ParseTree progTree = parser.prog(); //从prog开始解析
            //遍历完成，翻译结束
            System.out.println(progTree.toStringTree(parser));
/**         输出的分析树信息

 */

        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }


    }

    @Override
    public void parserLabeledExpr(ByteArrayInputStream byteArrayInputStream) {
        try {
            ANTLRInputStream  antlrInputStream = new ANTLRInputStream (byteArrayInputStream);
            LabeledExprLexer exprLexer= new LabeledExprLexer(antlrInputStream);
            CommonTokenStream tokens = new CommonTokenStream(exprLexer);
            LabeledExprParser parser = new LabeledExprParser(tokens);
            ParseTree progTree = parser.prog(); //从prog开始解析
            System.out.println(progTree.toStringTree(parser));

            CalculateLabeledExprVisitor visitor = new CalculateLabeledExprVisitor();
            visitor.visit(progTree);
            System.out.println("");
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }

    @Override
    public void parserRow(ByteArrayInputStream byteArrayInputStream, int col) {
        try {
            ANTLRInputStream  antlrInputStream = new ANTLRInputStream (byteArrayInputStream);
            RowLexer rowLexer= new RowLexer(antlrInputStream);
            CommonTokenStream tokens = new CommonTokenStream(rowLexer);
            RowParser parser = new RowParser(tokens,col);
//            parser.setBuildParseTree(false);
            ParseTree parserTree = parser.file();  //开始语法分析
            System.out.println(parserTree.toStringTree(parser));
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }
}
